/** 基础功能
 * 1. Promise 是一个类，在执行这个类的时候会传入一个执行器，这个执行器会立即执行
 *      - 执行器有两个参数，用来更改成功或失败后的状态
 *          -- resolve
 *          -- reject
 * 2. Promise 有三种状态
 *      - Pending   等待
 *      - Fulfilled 完成 ---> 完成之后的值：value
 *      - Rejected  失败 ---> 失败的原因： reason
 * 3. 状态流转只能由Pending --> Fulfilled、Pending --> Rejected，且一旦发生改变不可二次修改
 * 4. 状态的更改由Promise中使用resolve和reject两个函数决定
 * 5. then方法内部就是做状态判断
 *      - 如果状态是成功，调用成功的回调函数
 *      - 如果状态是失败，调用失败的回调函数
 */


//  1. 新建MyPromise类，传入执行器executor
// 2. Promise 有三种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
    constructor(executor) {
        // 执行器有两个参数
        executor(this.resolve, this.reject)
    }
    // 用来存储状态，初始为pending，后续状态的更改由resove和reject两个函数的调用来决定
    status = PENDING

    // 保存成功之后的值
    value = null
    // 保存失败的原因
    reason = null

    resolve = (value) => {
        if (this.status === PENDING) {
            // 3. 状态流转只能由Pending --> Fulfilled， 将成功的值进行保存
            // 4. 状态的更改由Promise中使用resolve和reject两个函数决定
            this.status = FULFILLED
            this.value = value
        }
    }
    reject = (reason) => {
        if (this.status === PENDING) {
            // 3. 状态流转只能由Pending --> Rejected， 将失败的原因进行保存
            // 4. 状态的更改由Promise中使用resolve和reject两个函数决定
            this.status = REJECTED
            this.reason = reason
        }
    }

    // 5. then方法内部就是做状态判断， 将成功和失败回调作为参数参入
    then = (onFulfilled, onRejected) => {
        if (this.status === FULFILLED) { // 如果状态是成功，调用成功的回调函数，并将成功值传入
            onFulfilled(this.value)
        }
        else if (this.status == REJECTED) { // 如果状态是失败，调用失败的回调函数，并将失败原因传入
            onRejected(this.reason)
        }

    }
}

const promise = new MyPromise((resolve, reject) => {
    resolve(`resolve: success`)
    reject(`reject: err`)
})

console.log(`--------------- 测试基本功能 ------------------`)
// 业务代码负责注册了onFulfilled和onRejected的回调函数
promise.then((value) => {
    console.log(value)
},
(reason) => {
    console.log(reason)
})

console.log(`--------------- 加入异步逻辑 ------------------`)
const promise1 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(`resolve: success`)
    }, 0);
    // reject(`reject: err`)
})
promise1.then((value) => {
    console.log(value)
},
(reason) => {
    console.log(reason)
})

// 没有经过异步处理，如果加入异步逻辑将会带来一些问题:
//     - 因为当前基础功能都是同步代码执行，当加入异步逻辑
//     - then()会马上执行，而setTimeout是异步代码，会延迟执行
//     - then()执行的时候，此时的状态status仍是pending